#!/bin/sh
# date: 2022/11/23
# auth: fearless11
# desc: docker deploy exporter and register/deregister to consul|kong

ip_local=$(/usr/sbin/ip add | grep inet | grep global | grep -Ev 'docker' | awk '{print $2}' | awk -F/ '{print $1}' | tail -1)
conf=conf/exporter.conf
consul_addr="127.0.0.1:8500"

get_random_port() {
    temp=0
    while [ $temp == 0 ]; do
        random=$(shuf -i 3000-4000 -n1)
        netstat -an | grep -w ":${random}" | grep 'LISTEN' && continue
        temp=${random}
    done
    export listen_port=$temp
}

parse_conf() {
    line=$(echo $1)
    echo $line | grep "^#" &>/dev/null && continue
    export target=$(echo $line | awk -F, '{print $1}')
    export ip=$(echo $line | awk -F, '{print $2}' | awk -F: '{print $1}')
    export port=$(echo $line | awk -F, '{print $2}' | awk -F: '{print $2}')
    export addr=$(echo $line | awk -F, '{print $2}')
    export docker_name=${target}_${ip}_${port}
    export remark=$(echo $line | awk -F, '{print $3}')
    export targetdept=$(echo $remark | awk -F- '{print $1}')
    export targetbiz=$(echo $remark | awk -F- '{print $2}')
    export targetenv=$(echo $remark | awk -F- '{print $3}')
    export version=$(echo $line | awk -F, '{print $4}')
    export user=$(echo $line | awk -F, '{print $5}' | awk -F';' '{print $1}')
    export passwd=$(echo $line | awk -F, '{print $5}' | awk -F';' '{print $2}')
    get_random_port
    export exporter=${ip_local}:${listen_port}
}

docker_start() {
    echo $(date +%F-%T) >/tmp/fall.ip
    while read line || [[ -n $line ]]; do
        parse_conf $line

        if [ $target != "node" ]; then
            # check if the network is connected
            which nc &>/dev/null || yum install nmap-ncat -y &> /dev/null
            nc -w 1 $ip $port </dev/null &>/dev/null && echo "ok $ip $port" || echo "fail $ip $port"
            # nc -w 1 ${ip} ${port} </dev/null &>/dev/null
            if [[ $? == 1 ]]; then
                echo "check network fail ${ip} ${port}" | tee -a /tmp/fall.ip
                continue
            fi
        fi

        # check if the container is running
        docker ps | grep ${docker_name} && continue
        echo ${docker_name}

        case ${target} in
        mysql)
            deploy_mysql
            consul_register
            ;;
        redis)
            deploy_redis
            consul_register
            ;;
        kafka)
            deploy_kafka
            consul_register
            ;;
        mongodb)
            deploy_mongodb
            consul_register
            ;;
        memcached)
            deploy_memcached
            consul_register
            ;;
        haproxy)
            deploy_haproxy
            consul_register
            ;;
        node)
            deploy_node_exporter
            consul_register
            ;;
        process)
            deploy_process_exporter
            consul_register
            ;;
        cadvisor)
            deploy_cadvisor
            consul_register
            ;;
        *)
            echo "${target} no match"
            continue
            ;;
        esac

    done <${conf}
}

docker_stop() {
    while read line || [[ -n $line ]]; do
        parse_conf $line
        docker stop ${docker_name}
        docker rm ${docker_name}
    done <${conf}
    sleep 10
    consul_deregister
}

docker_logs() {
    while read line || [[ -n $line ]]; do
        parse_conf $line
        echo ${docker_name}
        docker logs --tail 3 ${docker_name}
    done <${conf}
}

docker_register() {
    while read line || [[ -n $line ]]; do
        parse_conf $line
        docker ps | grep ${docker_name} &
        >/dev/null
        if [[ $? == 1 ]]; then
            echo "${docker_name} not running"
            continue
        fi

        pid=$(docker inspect ${docker_name} | grep -iw pid | awk -F: '{print $2}' | tr -d ',')
        export listen_port=$(netstat -nlput | grep "${pid}/" | awk -F: '{print $4}' | tr -d ' ')
        export exporter=${ip_local}:${listen_port}

        echo "listen_port: $listen_port $docker_name $exporter"
        consul_register &
        >/dev/null
    done <${conf}
}

consul_register() {
    curl --request PUT \
        --url http://${consul_addr}/v1/agent/service/register \
        --header 'content-type: "application/json"' \
        --data '{
    "id":"'${exporter}'",
    "name":"'${target}'",
    "tags":[
        "'${remark}'",
        "'${target}'",
        "'${ip}':'${port}'"
    ],
    "meta":{
       "biz":"'${remark}'"
    },
    "address":"'${ip_local}'",
    "port":'${listen_port}',
    "checks":[
        {
            "http":"http://'${exporter}'",
            "interval":"10s",
            "Timeout":"5s"
        }
    ]
}'
}

consul_deregister() {
    unhealthServiceID=$(curl -s -XGET http://${consul_addr}/v1/agent/checks?filter="Status==critical" | grep ServiceID | awk -F'"' '{print $4}')
    for serviceID in $(echo ${unhealthServiceID}); do
        curl -XPUT "http://${consul_addr}/v1/agent/service/deregister/${serviceID}"
    done
}

# mysql_exporter
# https://github.com/prometheus/mysqld_exporter
deploy_mysql() {
    # CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'XXXXXXXX' WITH MAX_USER_CONNECTIONS 3;
    # GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';
    if [ "x$version" == "x5.0" ]; then
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            -e DATA_SOURCE_NAME="$user:$passwd@($ip:$port)/" \
            prom/mysqld-exporter:0.8.1 \
            --web.listen-address=":${listen_port}"
    else
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            -e DATA_SOURCE_NAME="${user}:${passwd}@(${ip}:${port})/" \
            prom/mysqld-exporter:v0.12.1 \
            --web.listen-address=":${listen_port}"
    fi
}

# redis_exporter
# https://github.com/oliver006/redis_exporter
# https://github.com/fearless11/redis_exporter
deploy_redis() {
    # 默认自建无账号  1.0 密码  2.0 账号密码
    if [ "x$version" == "x1.0" ]; then
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            11expose11/redis_exporter:qcloud \
            -web.listen-address=:${listen_port} \
            -redis.addr=redis://${ip}:${port} \
            -redis.password=${passwd}
    elif [ "x$version" == "x2.0" ]; then
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            11expose11/redis_exporter:qcloud \
            -web.listen-address=:${listen_port} \
            -redis.addr=redis://${ip}:${port} \
            -redis.password=${user}@${passwd}
    else
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            oliver006/redis_exporter:v1.10.0 \
            -web.listen-address=:${listen_port} \
            -redis.addr=redis://${ip}:${port}
    fi
}

# kafka_exporter https://github.com/danielqsj/kafka_exporter
deploy_kafka() {
    if [ "x$version" == "x0.1" ]; then
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            danielqsj/kafka-exporter:v1.2.1 \
            --kafka.server=${ip}:${port} \
            --kafka.version=0.10.0.1 \
            --web.listen-address=":${listen_port}" \
            --log.level=info
    else
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            danielqsj/kafka-exporter:v1.2.1 \
            --kafka.server=${ip}:${port} \
            --web.listen-address=":${listen_port}" \
            --log.level=info
    fi
}

# mongodb_exporter https://github.com/percona/mongodb_exporter
deploy_mongodb() {
    if [ "x$version" == "x2.0" ]; then
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            -e MONGODB_URI="mongodb://${user}:${passwd}@${ip}:${port}" \
            percona/mongodb-exporter:0.9.0 \
            --web.listen-address=":${listen_port}"
    else
        docker run -d \
            --name ${docker_name} \
            -m 256m \
            --net=host \
            --restart=always \
            --log-opt max-size=100m \
            --log-opt max-file=10 \
            -e MONGODB_URI="mongodb://${ip}:${port}" \
            percona/mongodb-exporter:0.9.0 \
            --web.listen-address=":${listen_port}"
    fi
}

# memcached_exporter https://github.com/prometheus/memcached_exporter
deploy_memcached() {
    docker run -d \
        --name ${docker_name} \
        -m 256m \
        --net=host \
        --restart=always \
        --log-opt max-size=100m \
        --log-opt max-file=10 \
        prom/memcached-exporter:v0.8.0 \
        --memcached.address="${ip}:${port}" \
        --web.listen-address=":${listen_port}"
}

# haproxy_exporter https://github.com/prometheus/haproxy_exporter
deploy_haproxy() {
    docker run -d \
        -m 256m \
        --name ${docker_name} \
        --net=host \
        --restart=always \
        --log-opt max-size=100m \
        --log-opt max-file=10 \
        prom/haproxy-exporter:v0.12.0 \
        --haproxy.scrape-uri="http://127.0.0.1:8080/haproxy_stats/${ip}/haproxy1;csv" \
        --web.listen-address=:${listen_port}
}

# https://github.com/prometheus/node_exporter
deploy_node_exporter() {
    # default_port=9100
    docker run -d --name=${docker_name} \
        --net=host \
        --pid=host \
        -m 512m \
        --restart=always \
        --log-opt max-size=100m \
        --log-opt max-file=10 \
        --volume=$(pwd)/../conf/plugin:/plugin \
        --volume=/:/host:ro,rslave \
        --volume=/var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket \
        prom/node-exporter:v1.4.0 \
        quay.io/prometheus/node-exporter
    --path.rootfs=/host \
        --path.procfs=/proc \
        --path.sysfs=/sys \
        --web.disable-exporter-metrics \
        --collector.textfile.directory=/plugin \
        --collector.systemd \
        --log.level=info \
        --web.listen-address=":${listen_port}"
    export exporter=${ip_local}:${listen_port}
    echo ${ip_local}:${listen_port}
}

# process_exporter https://github.com/ncabatoff/process-exporter
deploy_process_exporter() {
    docker run -d --name=${docker_name} \
        --net=host \
        -m 2g \
        --restart=always \
        --log-opt max-size=100m \
        --log-opt max-file=10 \
        --privileged \
        --volume=/proc:/host/proc \
        --volume=$(pwd)/conf/:/conf \
        ncabatoff/process-exporter:v0.7.5 \
        --procfs=/host/proc \
        -threads=false \
        -conf.path=/conf/process_exporter.yaml \
        --web.listen-address=":9256"

    export exporter=${ip_local}:9256
}

# cadvisor https://github.com/google/cadvisor
deploy_cadvisor() {
    # mount -o remount,rw '/sys/fs/cgroup'
    # ln -s /sys/fs/cgroup/cpu,cpuacct /sys/fs/cgroup/cpuacct,cpu
    docker run -d \
        --name=${docker_name} \
        --restart=always \
        --net=host \
        -m "800m" \
        --log-opt max-size=100m \
        --log-opt max-file=10 \
        --volume=/:/rootfs:ro \
        --volume=/var/run:/var/run:rw \
        --volume=/sys:/sys:ro \
        --volume=/sys/fs/cgroup/:/sys/fs/cgroup/:ro \
        --volume=/var/lib/docker/:/var/lib/docker:ro \
        --volume=/dev/disk/:/dev/disk:ro \
        --privileged=true \
        --device=/dev/kmsg \
        --detach=true \
        google/cadvisor:0.36.0 \
        --port=8080 \
        -disable_metrics="disk,diskIO,network,tcp,udp,percpu,sched,process" \
        -docker_only=true \
        -raw_cgroup_prefix_whitelist="/docker"

    export exporter=${ip_local}:8080
}

usage() {
    if [ $# != 2 ]; then
        echo "usage: $0 $1 config"
        exit 1
    fi
    conf=$2
}

# default config: ../conf/exporter.conf
main() {
    case $1 in
    start)
        usage $*
        docker_start
        ;;
    stop)
        usage $*
        docker_stop
        ;;
    log)
        usage $*
        docker_log
        ;;
    reg)
        usage $*
        docker_register
        ;;
    dereg)
        consul_deregister
        ;;
    *)
        echo "start|stop|log|reg|dereg config"
        ;;
    esac
}

main $*
